using System;
using UnityEngine;

[AddComponentMenu("Scripts/Area Damage/AreaDamage")]
public class AreaDamage : MonoBehaviour
{
	public delegate void Listener(AreaDamage area);

	[Tooltip("Имя/ID, для получения доступа к конкретной области")]
	public string areaName;

	[Tooltip("Использовать несколько раз")]
	public bool reuse;

	[Tooltip("Локальные координаты центра области в метрах")]
	public Vector2 position = default(Vector2);

	[HideInInspector]
	public Vector2 positionHit = default(Vector2);

	[HideInInspector]
	public Vector2 positionHitLocal = default(Vector2);

	public float radius = 0.5f;

	[Range(0f, 360f)]
	public float angle;

	[Range(0f, 360f)]
	public float limitAngle;

	[Tooltip("здоровье для активации и повторного использования\nПри health = 0 - активировать область при запуске")]
	public float health = 1f;

	[HideInInspector]
	public float startHealth;

	[Tooltip("Необходимый наносимый урон для активации")]
	public float minDamage;

	[HideInInspector]
	public bool updateListOnStart;

	[HideInInspector]
	public ComponentArea[] listComps = new ComponentArea[0];

	public AreaScriptableComponent[] listScriptable = new AreaScriptableComponent[0];

	[Tooltip("События-идентификаторы, по которым можно найти области, выполняющие определенную функцию")]
	public string[] events = new string[0];

	private bool startMade;

	private bool hit;

	private float angleHit;

	private Listener onActivationListener;

	private AreaDamage[] listAreas = new AreaDamage[0];

	public string ToString()
	{
		return base.gameObject.name + ".AreaDamage(" + areaName + ":" + position.x + ";" + position.y + " [" + radius + "])";
	}

	public Vector2 GetWorldPosition()
	{
		return base.gameObject.transform.TransformPoint(position);
	}

	private void Awake()
	{
	}

	private void Start()
	{
		if (!startMade)
		{
			position.x = Mathf.Ceil(position.x * 1000f) / 1000f;
			position.y = Mathf.Ceil(position.y * 1000f) / 1000f;
			startHealth = health;
			int num = 0;
			for (num = 0; num < listComps.Length; num++)
			{
				if (listComps[num] != null)
				{
					listComps[num].OnStartArea(this);
				}
			}
			for (num = 0; num < listScriptable.Length; num++)
			{
				listScriptable[num].OnStartArea(this);
			}
		}
		startMade = true;
		if (health == 0f)
		{
			Activation(0f);
		}
	}

	public void Activation(float damage)
	{
		if (!startMade)
		{
			Start();
		}
		health = Mathf.Max(0f, health - damage);
		if (!startMade || health != 0f || !base.enabled)
		{
			return;
		}
		if (onActivationListener != null)
		{
			onActivationListener(this);
		}
		for (int i = 0; i < listComps.Length; i++)
		{
			if (listComps[i] != null)
			{
				listComps[i].Activation(this);
			}
		}
		for (int j = 0; j < listScriptable.Length; j++)
		{
			listScriptable[j].OnActivation(this);
		}
		base.enabled = reuse;
		health = startHealth;
	}

	public void Activation(string name)
	{
		listAreas = base.gameObject.GetComponents<AreaDamage>();
		int num = 0;
		for (num = 0; num < listAreas.Length; num++)
		{
			if (listAreas[num].areaName == name)
			{
				listAreas[num].Activation(listAreas[num].health);
			}
		}
		listAreas = null;
	}

	public void Activation(GameObject gameObject)
	{
		listAreas = gameObject.GetComponents<AreaDamage>();
		for (int i = 0; i < listAreas.Length; i++)
		{
			listAreas[i].Activation(listAreas[i].health);
		}
		listAreas = null;
	}

	public void Activation()
	{
		Activation(health);
	}

	public bool HitTestPoint(Vector2 point, float damage, float radius)
	{
		if (!base.enabled || damage < minDamage)
		{
			return false;
		}
		positionHit = point;
		point = base.gameObject.transform.InverseTransformPoint(point);
		positionHitLocal = point;
		hit = (radius >= Vector2.Distance(position, point));
		if (hit && (angle != 0f || limitAngle != 0f))
		{
			angleHit = Mathf.Atan2(point.y - position.y, point.x - position.x) * 57.29578f;
			angleHit = Mathf.Repeat(angleHit + 360f, 360f);
			hit = (angle <= angleHit && angleHit <= angle + limitAngle);
			angleHit += 360f;
			hit = (hit || (angle <= angleHit && angleHit <= angle + limitAngle));
		}
		if (hit)
		{
			Activation(damage);
		}
		return hit;
	}

	public bool HitTestPoint(Vector2 globalPoint, float damage)
	{
		return HitTestPoint(globalPoint, damage, radius);
	}

	public bool HitTestPoint(Vector2 globalPoint, float damage, float radius, string idEvent)
	{
		if (EventExists(idEvent))
		{
			return HitTestPoint(globalPoint, damage, radius);
		}
		return false;
	}

	public bool EventExists(string eventName)
	{
		if (areaName == eventName || string.IsNullOrEmpty(eventName))
		{
			return true;
		}
		for (int i = 0; i < events.Length; i++)
		{
			if (eventName == events[i])
			{
				return true;
			}
		}
		return false;
	}

	public bool IsConnected(ComponentArea component)
	{
		for (int i = 0; i < listComps.Length; i++)
		{
			if (listComps[i] == component)
			{
				return true;
			}
		}
		return false;
	}

	public bool IsConnected(AreaScriptableComponent component)
	{
		for (int i = 0; i < listScriptable.Length; i++)
		{
			if (listScriptable[i] == component)
			{
				return true;
			}
		}
		return false;
	}

	public void AddListener(Listener listener)
	{
		if (onActivationListener == null || onActivationListener == listener)
		{
			onActivationListener = listener;
		}
		else
		{
			onActivationListener = (Listener)Delegate.Combine(onActivationListener, listener);
		}
	}

	public void AddComponentListener<Type>(ComponentListener<Type> listener) where Type : class
	{
		for (int i = 0; i < listComps.Length; i++)
		{
			if (listComps[i] != null && listComps[i] is EventComponentArea<Type>)
			{
				EventComponentArea<Type>.temp = (listComps[i] as EventComponentArea<Type>);
				if (EventComponentArea<Type>.temp.onActivationListener == null || EventComponentArea<Type>.temp.onActivationListener == listener)
				{
					EventComponentArea<Type>.temp.onActivationListener = listener;
				}
				else
				{
					EventComponentArea<Type> temp = EventComponentArea<Type>.temp;
					temp.onActivationListener = (ComponentListener<Type>)Delegate.Remove(temp.onActivationListener, listener);
					EventComponentArea<Type> temp2 = EventComponentArea<Type>.temp;
					temp2.onActivationListener = (ComponentListener<Type>)Delegate.Combine(temp2.onActivationListener, listener);
				}
				EventComponentArea<Type>.temp = null;
			}
		}
	}

	public bool ComponentInList<Type>() where Type : class
	{
		int num = 0;
		for (num = 0; num < listComps.Length; num++)
		{
			if (listComps[num] != null && listComps[num] is Type)
			{
				return true;
			}
		}
		for (num = 0; num < listScriptable.Length; num++)
		{
			if (listScriptable[num] != null && listScriptable[num] is Type)
			{
				return true;
			}
		}
		return false;
	}

	public Type GetAreaComponent<Type>() where Type : class
	{
		int num = 0;
		for (num = 0; num < listComps.Length; num++)
		{
			if (listComps[num] != null && listComps[num] is Type)
			{
				return listComps[num] as Type;
			}
		}
		for (num = 0; num < listScriptable.Length; num++)
		{
			if (listScriptable[num] != null && listScriptable[num] is Type)
			{
				return listScriptable[num] as Type;
			}
		}
		return (Type)null;
	}

	public void Disable(string name)
	{
		listAreas = base.gameObject.GetComponents<AreaDamage>();
		for (int i = 0; i < listAreas.Length; i++)
		{
			if (listAreas[i].areaName == name)
			{
				listAreas[i].enabled = false;
			}
		}
		listAreas = new AreaDamage[0];
	}

	public void Enable(string name)
	{
		listAreas = base.gameObject.GetComponents<AreaDamage>();
		for (int i = 0; i < listAreas.Length; i++)
		{
			if (listAreas[i].areaName == name)
			{
				listAreas[i].enabled = true;
			}
		}
		listAreas = new AreaDamage[0];
	}

	public void Destroy(string name)
	{
		listAreas = base.gameObject.GetComponents<AreaDamage>();
		for (int i = 0; i < listAreas.Length; i++)
		{
			if (listAreas[i].areaName == name)
			{
				UnityEngine.Object.Destroy(listAreas[i]);
			}
		}
		listAreas = new AreaDamage[0];
	}
}
